package org.hiberlyzer.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hiberlyzer.DataColumn;
import org.hiberlyzer.DataSet;
import org.hibernate.Session;
import org.hibernate.metadata.ClassMetadata;

/**
 * A DataSet that may contain simple properties as well as entities in the same
 * set of results.  Entity properties will not be treated as individual columns
 * in this DataSet.
 */
public class HybridDataSet implements DataSet
{
	private List<Object> _results;
	private Session _session;
	private List<DataColumn> _columns;
	
	public HybridDataSet(List<Object> results, Session session)
	{
		this._results = results;
		this._session = session;
		determineColumns();
	}

	public List<DataColumn> getColumns()
	{
		return Collections.unmodifiableList(_columns);
	}

	public int getResultCount()
	{
		return _results.size();
	}

	public Object getValue(int rowIndex, int columnIndex)
	{
		if(_columns.size() > 1)
		{
			return ((Object[]) _results.get(rowIndex))[columnIndex];
		}
		return _results.get(rowIndex);
	}
	
	private void determineColumns()
	{
		_columns = new ArrayList<DataColumn>();
		
		Object result = _results.get(0);
		if(result instanceof Object[])
		{
			Object[] row = (Object[]) result;
			for(int i = 0; i < row.length; i++)
			{
				_columns.add(makeColumn("Column" + (i+1), row[i]));
			}
		}
		else
		{
			_columns.add(makeColumn("Column1", result));
		}
	}
	
	private DataColumn makeColumn(String name, Object value)
	{
		Class classOfValue = Object.class;
		if(value != null)
		{
			classOfValue = value.getClass();
		}

		// Collection columns cannot be returned by an arbitrary HQL query like the one
		// that would cause a HybridDataSet to be used.  We only have to worry about
		// entity and simple data columns.
		ClassMetadata metadata = _session.getSessionFactory().getClassMetadata(classOfValue);
		if(metadata != null)
		{
			return new EntityDataColumn(name, metadata, _session.getEntityMode());
		}
		else
		{
			return new SimpleDataColumn(name, classOfValue);
		}
	}
}
